/*******************************************************************************
 * Copyright (c) 2014 Francesco Gabbrielli.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Francesco Gabbrielli - initial API and implementation
 ******************************************************************************/
package it.francescogabbrielli.android.solidalapp.home;

import java.util.Timer;
import java.util.TimerTask;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.gms.maps.model.LatLng;

import it.francescogabbrielli.android.solidalapp.Constants;
import it.francescogabbrielli.android.solidalapp.DataEvent;
import it.francescogabbrielli.android.solidalapp.EndpointsLoader;
import it.francescogabbrielli.android.solidalapp.EndpointsUtils;
import it.francescogabbrielli.android.solidalapp.IntentAction;
import it.francescogabbrielli.android.solidalapp.MessageActivity;
import it.francescogabbrielli.android.solidalapp.NetworkUtils;
import it.francescogabbrielli.android.solidalapp.R;
import it.francescogabbrielli.android.solidalapp.SolidalApp;
import it.francescogabbrielli.android.solidalapp.SolidalApp.DataKey;
import it.francescogabbrielli.android.solidalapp.deviceendpoint.model.Device;
import it.francescogabbrielli.android.solidalapp.file.RequestFileActivity;
import it.francescogabbrielli.android.solidalapp.profile.RequestProfileActivity;
import it.francescogabbrielli.android.solidalapp.profileendpoint.model.Profile;
import it.francescogabbrielli.android.solidalapp.requestendpoint.model.Request;
import it.francescogabbrielli.android.solidalapp.response.ResponseActivity;
import it.francescogabbrielli.android.solidalapp.responseendpoint.model.Response;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.Loader;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;

public class HomeActivity extends MessageActivity<Request> 
	implements HomeFragmentListener {
	
	class CheckExpiry extends TimerTask {		
		@Override
		public void run() {
			
			final Request req = (Request) app.getData(DataKey.REQUEST);
			if (req==null) {
				cancel();
				return;
			}
			
			if (req.getId()!=null && req.getExpiry()<System.currentTimeMillis() && !req.getAccepted()) {
				new Handler(getApplicationContext().getMainLooper()).post(new Runnable() {
					@Override
					public void run() {
						// reset request
						req.setId(null);
						req.setExpired(true);
						app.alert(R.string.request_expired);
						app.fireDataChanged(new DataEvent(this, DataKey.REQUEST, true));
					}
				});
				cancel();
			}
		}
	}
	
	private Timer checkExpiry;
	
	private void scheduleCheckExpiry() {
		if (checkExpiry==null) {
			checkExpiry = new Timer();
			checkExpiry.scheduleAtFixedRate(new CheckExpiry(), 600, 60000);
		}
	}
	
	private void descheduleCheckExpiry() {
		if (checkExpiry!=null) {
			checkExpiry.cancel();
			checkExpiry = null;
		}
	}
	
	/** Current sending request, ready for dispatch */
	private Request request;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.baseactivity_home);

		if (app.getStatus().getGcmId()==null)
			checkPlayServices();
		
		ActionBar actionBar = getSupportActionBar();
		
	    // two fragments layout
	    if (!"".equals(getString(R.string.home_tab_map))) {
	    	actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
	    	addTab(R.string.home_tab_request, R.id.home_tab_container, "request", RequestDataFragment.class);
	    	addTab(R.string.home_tab_map, R.id.home_tab_container, "map", RequestMapFragment.class);
	    } else {
	    	RequestFragment homeFragment = (RequestFragment) getSupportFragmentManager().findFragmentByTag("request");
	    	if(homeFragment==null) {
	    		homeFragment = new RequestFragment();
		    	FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
		    	ft.add(R.id.home_tab_container, homeFragment, "request");
		    	ft.commit();
	    	}
	    }
//	    addTab(R.string.home_tab_profile, R.id.home_tab_container, "profile", ProfileFragment.class);
//	    addTab(R.string.home_tab_debug, R.id.home_tab_container, "debug", DebugFragment.class);

	    if (savedInstanceState!=null && actionBar.getNavigationMode()==ActionBar.NAVIGATION_MODE_TABS) {
	    	int pos = savedInstanceState.getInt("tabSelected");
	    	actionBar.selectTab(actionBar.getTabAt(pos));
	    }
	    
		switch(IntentAction.valueOf(getIntent())) {
		case GCM_RESPONSE_RECEIVED:
			forwardNotification();
			break;
		default:
		}
			    
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getSupportMenuInflater();
		inflater.inflate(R.menu.home, menu);
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.action_simulate:
			SharedPreferences prefs = getSharedPreferences(SolidalApp.class.getName(), MODE_PRIVATE);
			int n = prefs.getInt("simulation", 0) + 1;
			prefs.edit().putInt("simulation", n).commit();
			Location loc = app.getStatus().getLocation();
			Request req = new Request();
			req.setCredits(1 + (int) (Math.random()*5));
			req.setDetails("Simulated position n."+n);
			req.setDuration(60);
			req.setLatitude(loc.getLatitude() + 0.004d * Math.random() * Math.signum(Math.random()-0.5d));
			req.setLongitude(loc.getLongitude() + 0.004d * Math.random() * Math.signum(Math.random()-0.5d));
			req.setManualLocation(true);
			req.setMessage("Simulation n."+n);
			req.setRegistrationId(app.getStatus().getGcmId());
			req.setTimestamp(System.currentTimeMillis());
			send(req);
			return true;
		case R.id.action_reload:
			retryReload(true);
			return true;
		case R.id.action_profile:
			startActivity(new Intent(this, RequestProfileActivity.class));
			return true;
		case R.id.action_requests:
			startActivity(new Intent(this, ResponseActivity.class));
			return true;
		case R.id.action_clear:
			Toast.makeText(this, "Pulisco la richiesta corrente", Toast.LENGTH_SHORT).show();
			request = null;
			app.setData(DataKey.REQUEST, null);
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		if(getSupportActionBar().getNavigationMode()==ActionBar.NAVIGATION_MODE_TABS)
			outState.putInt("tabSelected", getSupportActionBar().getSelectedTab().getPosition());
	}
	
	@Override
	protected void onNewIntent(Intent intent) {
		
		super.onNewIntent(intent);
		
		switch(IntentAction.valueOf(intent)) {
		case GCM_RESPONSE_RECEIVED:
			app.alert(R.string.map_marker_accepted);
			retryReload(true);
			break;
			
		default:
		}
		
	}
	
	@Override
	public void onDataChanged(DataEvent event) {
		
		super.onDataChanged(event);
		
		switch (event.getKey()) {
		case FILE_RESPONSE:
			Response res = (Response) app.getData(DataKey.FILE_RESPONSE);
			if (res!=null && res.getCompleted()) {
				SharedPreferences prefs = getSharedPreferences(SolidalApp.class.getCanonicalName(), MODE_PRIVATE);
				prefs.edit().putBoolean(Constants.RESET_REQUEST, true).commit();
				app.setData(DataKey.REQUEST, null);
				app.setData(DataKey.FILE_RESPONSE, null);
				app.setData(DataKey.ADDRESS_LOCATION_MANUAL, null);
				app.setData(DataKey.ADDRESS_TEXT_MANUAL, null);
				app.setData(DataKey.ADDRESS_LOCATION, app.getStatus().getLocation());
				app.setData(DataKey.CHAT_REQUEST, null);
				retryReload(true);
			}
			break;
			
		case REQUEST:
			Request req = (Request) app.getData(DataKey.REQUEST);
			if (req!=null) {
				scheduleCheckExpiry();
			} else {
				descheduleCheckExpiry();
			}
			break;
			
		default:
			break;
		}
	}

	/**
	 * Check a request and send it the to server endpoint
	 * 
	 * @param request
	 * 				the client request object
	 */
	@Override
	public void send(Request request) {
		
		this.request = null;
		
		hideKeyboard();
		
		// Check network
		if (app.getStatus().getNetworkStatus()!=NetworkUtils.Status.CONNECTED) {
			Toast.makeText(this, R.string.check_network, Toast.LENGTH_SHORT).show();
			return;
		}
				
		// Check registration
		Device device = (Device) app.getData(DataKey.DEVICE);
		if (device==null || app.getStatus().getGcmId()==null) {
			startActivity(new Intent(this, RequestProfileActivity.class));
			Toast.makeText(this, R.string.check_profile, Toast.LENGTH_SHORT).show();
			return;
		}
		
		// Check profile
		Profile profile = (Profile) app.getData(DataKey.PROFILE);
		if (profile==null) {
			startActivity(new Intent(this, RequestProfileActivity.class));
			Toast.makeText(this, R.string.check_profile, Toast.LENGTH_SHORT).show();
			return;
		}
		
		// Check username & phone
//		String phone = device.getTelephoneNumber();
//		if (phone==null || "".equals(phone))
//			phone = profile.getDefaultPhone();
		request.setSender(profile.getUsername());
		request.setSenderId(profile.getProfileId());
		
		// Check message
		if ("".equals(request.getMessage())) {
			Toast.makeText(this, R.string.check_message, Toast.LENGTH_SHORT).show();
			return;
		}
		
		// Check credits
		if (0 == request.getCredits()) {
			Toast.makeText(this, R.string.request_check_credits, Toast.LENGTH_SHORT).show();
			return;
		}
		
		// Check address
		if ("".equals(request.getDetails())) {
			Toast.makeText(this, R.string.request_check_address, Toast.LENGTH_SHORT).show();
			return;
		}
		
		// Show map if not visible
		if (getSupportActionBar().getNavigationMode()==ActionBar.NAVIGATION_MODE_TABS) {
			Tab t = getSupportActionBar().getTabAt(1);
			if("map".equals(t.getTag()))
				selectTab(1);
		}

		// Show confirm dialog
		this.request = request;
		new AlertDialog.Builder(this)
			.setMessage(R.string.request_alert_message)
			.setTitle(request.getDetails())
			.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
				@Override
	            public void onClick(DialogInterface dialog, int id) {
	            	send();
	            }
	        }).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int id) {
	            	Toast.makeText(HomeActivity.this, 
        			R.string.request_check_address, 
        			Toast.LENGTH_SHORT).show();
				}
			}).create().show();
	}
	
	/**
	 * Send the request with new coordinates
	 * 
	 * @param pos
	 * 				the new coordinates
	 */
	@Override
	public void send(LatLng pos) {
		request.setLatitude(pos.latitude);
		request.setLongitude(pos.longitude);
		String address = (String) app.getData(DataKey.ADDRESS_TEXT);
		EditText detailsEdit = (EditText) findViewById(R.id.request_details_edit);
		if (detailsEdit!=null)
			address = detailsEdit.getText().toString();
		request.setDetails(address);
		send();
	}

	/**
	 * Send the current checked request
	 */
	private void send() {
		
	    try {
	    	
	    	// clear with a new temp request the request previously sent
	    	Request temp = new Request();
	    	temp.setLatitude(request.getLatitude());
	    	temp.setLongitude(request.getLongitude());
	    	request.setExpired(false);//correct previous expired request if any
	    	app.setData(DataKey.REQUEST, temp);
	    	
	    	IntentAction.ENDPOINTS_SEND_REQUEST.start(
		    		HomeActivity.this, 
		    		EndpointsUtils.toBundle(request),
		    		0);
	    	
	    } catch(Exception e) {
	    	
	    	request = null;
	    	app.setData(DataKey.REQUEST, null);
	    	Log.e(SolidalApp.TAG, "Error: "+e, e);
		    Toast.makeText(HomeActivity.this, "Error: "+e, Toast.LENGTH_SHORT).show();
		    
	    }
	    
	}
	
	@Override
	public void openFile() {
		Intent intent = new Intent(this, RequestFileActivity.class);
		startActivity(intent);
	}
	
	@Override
	public Fragment selectTab(int position) {
	    ActionBar actionBar = getSupportActionBar();
	    Tab t = actionBar.getTabAt(position);
	    actionBar.selectTab(t);
	    return getSupportFragmentManager().findFragmentByTag((String) t.getTag());
	}
	
	@Override
	public Request getRequest() {
		return request;
	}
	
	@Override
	protected int getLoaderId() {
		return Constants.LOADER_REQUEST;
	}
	
	@Override
	public Loader<Request> onCreateLoader(int id, Bundle data) {
		return new EndpointsLoader<Request>(this, Request.class)
			.setFilters(data)
			.setMethod("getLast");
	}

	@Override
	public void onLoadFinished(final Loader<Request> loader, final Request result) {
		
		// make sure it is executed when activity is resumed
		addOnResumeAction(new Runnable() {
			
			public void run() {
				
				if (result!=null && !result.getCompleted()) {
					
					descheduleCheckExpiry();
					
					final ActionBar actionBar = getSupportActionBar();
					
					if (actionBar.getSelectedNavigationIndex()==0 && actionBar.getNavigationMode()==ActionBar.NAVIGATION_MODE_TABS) {
						Handler h = new Handler(loader.getContext().getMainLooper());
						h.post(new Runnable() {
							@Override
							public void run() {
								actionBar.setSelectedNavigationItem(1);
							}
						});
					}
					
					app.setData(DataKey.ADDRESS_LOCATION_MANUAL, true);
					app.setData(DataKey.ADDRESS_LOCATION, app.getStatus()
							.newLocation(result.getLatitude(), result.getLongitude()));
					app.setData(DataKey.ADDRESS_TEXT_MANUAL, true);
					app.setData(DataKey.REQUEST, result);
				} else {
					app.setData(DataKey.REQUEST, null);
				}
			}
		});
	}

	@Override
	public void onLoaderReset(Loader<Request> loader) {
		Log.i(SolidalApp.TAG, "Loader Reset: "+getClass().getSimpleName());
//		loader.reset();
	}
	
}
